#include <Ape/Collections/Stack.h>
#include <Ape/Exception.h>

#include <Ape/MT/Mutex.h>

namespace Ape {
	namespace Collections {
		using Ape::MT::MutexLock;
		
		struct StackElement {
			void* Value;
			StackElement* Lower;
			StackElement* Upper;
			
			static StackElement* create (void* value) {
				StackElement* elt = new StackElement;
				elt->Value = value;
				elt->Lower = NULL;
				elt->Upper = NULL;
				return elt;
			}
		};
		
		StackImpl::StackImpl()
				: m_Top (NULL),
				m_Height (0)
		{
			InitObjectMutex();
		}
		StackImpl::~StackImpl()
		{}
		
		void StackImpl::push (void* elt) {
			MutexLock lock (GetObjectMutex() );
			if (!m_Top) {
				m_Top = StackElement::create (elt);
			}
			else {
				StackElement* se = StackElement::create (elt);
				m_Top->Upper = se;
				se->Lower = m_Top;
				m_Top = se;
			}
			m_Height++;
		}
		void* StackImpl::pop() {
			MutexLock lock (GetObjectMutex() );
			if (!m_Top) {
				throw Exception (L"Stack is empty");
			}
			StackElement* fetched = m_Top;
			m_Top = fetched->Lower;
			if (m_Top) {
				m_Top->Upper = NULL;
			}
			void* ret = fetched->Value;
			delete fetched;
			m_Height--;
			return ret;
		}
		
		size_t StackImpl::height() const {
			return m_Height;
		}
		
		void StackImpl::_Dump (bool verbose) const {
			Object::_Dump (verbose);
			DUMP_NON_V_TYPE;
			
			printf ("\t\tHeight:\t%i\n", height() );
		}
	}
}
